/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.*;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import javax.imageio.ImageIO;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;
import src.Malla;
import src.JPanelDibujo;

/**
 *
 * @author Alejandro Naranjo
 */
public class Archivo
{
    private JFrame parent;
    private Gson gson;
    private ArrayList<String> rutas;
    private ArrayList<String> rutasDirectorios;
    //private ArrayList<String> rutas;

    public Archivo(JFrame parent) {
        this.parent = parent;
        this.gson = new GsonBuilder().setPrettyPrinting().create();
        rutas = new ArrayList();
        rutasDirectorios = new ArrayList();
        
    }
    
    public Malla abrir(){
        //usamos un filechooser para buscar la ubicacion donde se encuentra el archivo
        JFileChooser fc = new JFileChooser();
        //Le aplicamos un filtro para JSON files - la extension es facil de cambiar
        fc.addChoosableFileFilter( new FileNameExtensionFilter( "Archivos .MALLA", "malla", "MALLA" ) );
        int seleccion = fc.showOpenDialog( this.parent );
        if( seleccion == JFileChooser.APPROVE_OPTION )
        {
            String ubicacion = fc.getSelectedFile().getAbsolutePath();
            File file = new File(ubicacion);
            //descomprimirZip(file);
            File directorioTemporal = new File(file.getParent()+"/"+obtenerNombre(file.getName())+"Temporal");
            directorioTemporal.mkdir();
            this.rutasDirectorios.add(""+directorioTemporal);
            unZip(file,directorioTemporal);
            String archivoGson = encontrarGson(directorioTemporal);
                try {

                    BufferedReader archivoJsonBufferedReader;
                    archivoJsonBufferedReader = new BufferedReader( new FileReader(archivoGson) );
                    Malla malla = this.gson.fromJson(archivoJsonBufferedReader, Malla.class);
                    malla.setRutaGuardado(ubicacion);
                    System.out.println(malla.getRutaGuardado());
                    archivoJsonBufferedReader.close();
                    eliminarFicheroGSon(new File(archivoGson));
                    return malla;
                } catch (IOException ex) {
                    Logger.getLogger(Archivo.class.getName()).log(Level.SEVERE, null, ex);
                    return null;
                }
                
               
        }
        return null;
    }
    
    public Malla abrir( String ubicacion )
    {
        File file = new File(ubicacion);
        //descomprimirZip(file);
        File directorioTemporal = new File(file.getParent()+"/"+obtenerNombre(file.getName())+"Temporal");
        directorioTemporal.mkdir();
        this.rutasDirectorios.add(""+directorioTemporal);
        unZip(file,directorioTemporal);
        String archivoGson = encontrarGson(directorioTemporal);
        try {
            BufferedReader archivoJsonBufferedReader;
            archivoJsonBufferedReader = new BufferedReader( new FileReader(archivoGson) );
            Malla malla = this.gson.fromJson(archivoJsonBufferedReader, Malla.class);
            malla.setRutaGuardado(ubicacion);
            System.out.println(malla.getRutaGuardado());
            archivoJsonBufferedReader.close();
            eliminarFicheroGSon(new File(archivoGson));
            return malla;
        } 
        catch (IOException ex) {
            Logger.getLogger(Archivo.class.getName()).log(Level.SEVERE, null, ex);
            return null;
        }
    }
    
    private String encontrarGson(File directorioTemporal){
        File[] ficheros = directorioTemporal.listFiles();
        for(File fichero : ficheros){
            String fich = ""+fichero;
            if(fichero.length() > 4){
                String aux = fich.substring(fich.length()-4);
                if (aux.equals("gson")){
                    return fich;
                }
            }
        }
        return null;
    }
    
   public void unZip(File file, File directorioTemporal){
   final int BUFFER = 2048;
      try {
         BufferedOutputStream dest = null;
         FileInputStream fis = new FileInputStream(file);
         ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
         ZipEntry entry;
         while((entry = zis.getNextEntry()) != null) {
            System.out.println("Extracting: " +entry);
            
            int count;
            byte data[] = new byte[BUFFER];
            // write the files to the disk
            FileOutputStream fos = new 	      FileOutputStream(directorioTemporal+"/"+entry.getName());
            dest = new               BufferedOutputStream(fos, BUFFER);
            while ((count = zis.read(data, 0, BUFFER))               != -1) {
               dest.write(data, 0, count);
            }
            String nuevaRuta = directorioTemporal+"/"+entry.getName();
            rutas.add(nuevaRuta);
             
            dest.flush();
            dest.close();
         }
         zis.close();
      } catch(Exception e) {
         e.printStackTrace();
      }
   }
   
   public void eliminarDescompresionZip(){
       File file;
       
       for(String ruta:rutas){
           System.out.println(ruta);
           file = new File(ruta);
           if(file.exists()){
               file.delete();
           }
       }
       for(String directorio : rutasDirectorios){
           file = new File(directorio);
           if(file.exists()){
               file.delete();
           }
       }
       
   }

   
   public void eliminarFicheroMalla(File file){
       if(file.exists()){
           file.delete();
       }
       file = new File(file.getParent()+"/"+obtenerNombre(file.getName()));
       if(file.exists()){
           file.delete();
       }
   }
   public void eliminarFicheroGSon(File file){
       if(file.exists()){
           file.delete();
       } 
   }
    public String obtenerNombre(String nombre){
        int largo = nombre.length();
        nombre = nombre.substring(0,largo-6);
        return nombre;
    }

    public Malla guardar(Malla malla)
    {
        File file = new File(malla.getRutaGuardado());
        System.out.println(malla.getRutaGuardado()); 
        try
        {
            malla = guardarZip(malla, file,true);
        }
        catch(Exception e)
        {
            JOptionPane.showMessageDialog(this.parent, "No es posible guardar", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
        }
        return malla;
    }
    
    public Malla guardarComo(Malla mallaSeleccionada )
    {
        //FileChooser nuevamente para buscar ubicacion donde guardar
        JFileChooser fc = new JFileChooser();
        fc.setCurrentDirectory(new File("."));//situarnos en el directorio actual
        //fc.addChoosableFileFilter(new fGuardarImagen() );//Introducimos el filtro que queremos aplicar
        fc.addChoosableFileFilter(null);
        //fc.setSelectedFile (fFile);//Asignamos el nombre dle archivo por defecto a guardar
        int returnVal = fc.showSaveDialog(this.parent);//Abrimos el selector de diálogo 
        //String ruta = fFile.getPath();
        //Introducimos el filtro que queremos aplicar
        fc.addChoosableFileFilter( new FileNameExtensionFilter( "Archivos .MALLA", "malla", "MALLA" ) );
        //Abrimos el selector de diálogo 
        File fFile = fc.getSelectedFile();
        //Vemos si es que se ha seleccionado correctamente el archivo
        if (returnVal == JFileChooser.APPROVE_OPTION)
        {
            //Pregunta si este ya existe
            if( fFile.exists() )
            {
                //Pregunta por reemplazar
                int response = JOptionPane.showConfirmDialog(null,"El archivo ya existe.¿Quieres reemplazarlo?",
                                                                "Confirmar Reemplazo",
                                                                JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE);
                if( response == 0 ){
                    
                    try
                    {
                        mallaSeleccionada = guardarZip(mallaSeleccionada, fFile, true);
                        String direccion = ""+fFile;
                        mallaSeleccionada.setRutaGuardado(direccion);
                        System.out.println(mallaSeleccionada.getRutaGuardado());
                        return mallaSeleccionada;
                    }
                    catch(Exception e)
                    {
                        JOptionPane.showMessageDialog(this.parent, "No es posible guardar en archivo seleccionado", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
                    }
                }
            }
            else{
                try
                    {
                        mallaSeleccionada = guardarZip(mallaSeleccionada, fFile,false);
                        String direccion = ""+fFile+".malla";
                        mallaSeleccionada.setRutaGuardado(direccion);
                        System.out.println(mallaSeleccionada.getRutaGuardado());
                        return mallaSeleccionada;
                    }
                catch(Exception e)
                    {
                        JOptionPane.showMessageDialog(this.parent, "No es posible guardar en archivo seleccionado", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
                    }
            }
            
        }

        return mallaSeleccionada;
    }
    
    //voy a crear el alrchivo gson en este metodo
    public Malla guardarZip(Malla malla, File file, boolean existe){
        
        FileOutputStream fos;
        FileInputStream fis;
        ZipOutputStream zos;
        ZipEntry ze;
        byte [] buffer;
        int leido;
        try
        {
            File directorioTemporal;
            if(existe){
                eliminarFicheroMalla(file);
                directorioTemporal = new File (file.getParent()+"/"+obtenerNombre(file.getName())+"Temporal");    
                directorioTemporal.mkdir();
                this.rutasDirectorios.add(""+directorioTemporal);
            }
            else{
                directorioTemporal = new File (file.getParent()+"/"+file.getName()+"Temporal");   
                directorioTemporal.mkdir();
                this.rutasDirectorios.add(""+directorioTemporal);
            }
            
            fos = (!existe)?new FileOutputStream(file+".malla") : new FileOutputStream(file);
            zos = new ZipOutputStream(fos);
            
            File archivoFicha;
            ArrayList<String> fichasAValidar = new ArrayList();
            for(int i = 1; i <= malla.getDuracion();i++){//Ciclo que recorre los años de duración de la carrera.
                if (malla.getRamos().containsKey(i)){//Verificamos si existe un año con algun curso ya inscrito.
                    for(int j = 0; j < malla.getRamosNivel(i).size();j++){//Recorre todas los ramos para el año correspondiente.
                        if(!malla.getRamosNivel(i).get(j).getRutaFicha().equals("")){
                            archivoFicha = new File(malla.getRamosNivel(i).get(j).getRutaFicha());
                            malla.getRamosNivel(i).get(j).setRutaFicha(directorioTemporal+"/"+archivoFicha.getName());
                            System.out.println(malla.getRamosNivel(i).get(j).getRutaFicha());
                            if(!fichasAValidar.contains(""+archivoFicha.getName())){
                                fis = new FileInputStream(archivoFicha);

                                ze = new ZipEntry(archivoFicha.getName());
                                zos.putNextEntry(ze);
                                buffer = new byte[1024];
                                leido = 0;
                                while(0 < (leido = fis.read(buffer))){
                                    zos.write(buffer, 0, leido);

                                }
                                fichasAValidar.add(""+archivoFicha.getName());
                                fis.close();
                                zos.closeEntry();  
                            }
                            
                        }        
                    }
                }
            }
            
            String outPut = this.gson.toJson( malla );
            FileWriter fw = new FileWriter(directorioTemporal+"/"+malla.getNombre()+".gson");
            fw.write( outPut );
            fw.close();
            
            
            
            fis =  new FileInputStream(directorioTemporal+"/"+malla.getNombre()+".gson");
            
            
            
            ze = new ZipEntry(malla.getNombre()+".gson");
            zos.putNextEntry(ze);
            
            
            
            buffer = new byte[1024];
            leido = 0;
            while(0 < (leido = fis.read(buffer))){
                zos.write(buffer, 0, leido);
                
            }
            fis.close();
            zos.closeEntry();
            
            zos.close();
            
            if(existe){
                unZip(file,directorioTemporal);
                eliminarFicheroGSon(new File(directorioTemporal+"/"+malla.getNombre()+".gson"));
            }
            else{
                file = new File(file+".malla");
                unZip(file,directorioTemporal);
                eliminarFicheroGSon(new File(directorioTemporal+"/"+malla.getNombre()+".gson"));
                
            }
            //unZip(file);
        }
        catch(IOException e)
        {
                    JOptionPane.showMessageDialog(this.parent, "Error de Escritura", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
        }
        return malla;
    }
   
    
    public void escribirFichero(File file, String outPut)
    {
        try
        {
            System.out.println(file);
            FileWriter fw =  new FileWriter(file);
            fw.write( outPut );
            fw.close();
        }
        catch (IOException e)
        {
            JOptionPane.showMessageDialog(this.parent, "Error de Escritura", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
        }
    }
    
    public void imprimir(JPanelDibujo panelDibujo )
    {
        PrinterJob job = PrinterJob.getPrinterJob();
        job.setPrintable(panelDibujo);
        panelDibujo.repaint();
        if (job.printDialog()) {
            try {
                job.print();
                panelDibujo.resetcolor();
            } catch (PrinterException eprinter) {
                JOptionPane.showMessageDialog(this.parent, "Error Al Intentar Imprimir", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
            }
        }
    }
    
    public void exportar(JPanelDibujo panelDibujo )
    {
        JFileChooser fc = new JFileChooser();
        int result = fc.showSaveDialog(panelDibujo);
        if( result == JFileChooser.APPROVE_OPTION )
        {
            this.guardarEn(fc.getSelectedFile(), panelDibujo );
            panelDibujo.resetcolor();
        }
    }
    
    public void guardarEn(File selectedFile, JPanelDibujo panelDibujo )
    {
        panelDibujo.quitarSeleccionador();
        try {
            BufferedImage bi = new BufferedImage(panelDibujo.getWidth(), panelDibujo.getHeight(), BufferedImage.TYPE_INT_RGB);
            Graphics g = bi.getGraphics();
            g.setColor(Color.black);
            panelDibujo.setBackground(Color.white);
            panelDibujo.paint(g);
            File f = new File( selectedFile.getPath() + ".PNG" );
            ImageIO.write( bi, "PNG", f );
        } 
        catch (IOException ex){
            JOptionPane.showMessageDialog(this.parent, "Error Al Intentar Imprimir", this.parent.getTitle(), JOptionPane.INFORMATION_MESSAGE);
        }
    }
    
    public void ayuda()
    {
        JOptionPane.showMessageDialog(this.parent, "Para cualquier problema consulta al proveedor.", "Ayuda", JOptionPane.INFORMATION_MESSAGE);
    }
    
    public void salir()
    {
        //Quieres salir?
        int response = JOptionPane.showConfirmDialog(null,"¿Quieres cerrar el programa?",
                                                                "Confirmar Salir",
                                                                JOptionPane.OK_CANCEL_OPTION,JOptionPane.QUESTION_MESSAGE);
        //Respuesta positiva
        if( response == 0 )
        {
            this.parent.dispose();
            System.exit(0);
        }
    }
}
